package com.lagou.pojo;

import com.lagou.sqlSession.DefaultSqlSession;
import com.lagou.sqlSession.SqlSession;

import javax.sql.DataSource;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Configuration {

    private DataSource dataSource;

    /*
    *   key: statementid  value:封装好的mappedStatement对象
     * */
    Map<String,MappedStatement> mappedStatementMap = new HashMap<>();

    public DataSource getDataSource() {
        return dataSource;
    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public Map<String, MappedStatement> getMappedStatementMap() {
        return mappedStatementMap;
    }

    public void setMappedStatementMap(Map<String, MappedStatement> mappedStatementMap) {
        this.mappedStatementMap = mappedStatementMap;
    }

    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        Object proxyInstance = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{type}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 底层都还是去执行JDBC代码 //根据不同情况，来调用selctList或者selectOne
                // 准备参数 1：statmentid :sql语句的唯一标识：namespace.id= 接口全限定名.方法名
                // 方法名：findAll
                String methodName = method.getName();
                String className = method.getDeclaringClass().getName();

                String statementId = className+"."+methodName;
                MappedStatement mappedStatement = mappedStatementMap.get(statementId);
                SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
                switch (sqlCommandType){
                    case SELECT:
                        // 准备参数2：params:args
                        // 获取被调用方法的返回值类型
                        Type genericReturnType = method.getGenericReturnType();
                        // 判断是否进行了 泛型类型参数化
                        if(genericReturnType instanceof ParameterizedType){
                            List<Object> objects = sqlSession.selectList(statementId, args);
                            return objects;
                        }

                        return sqlSession.selectOne(statementId,args);
                    case INSERT:
                        return sqlSession.insert(statementId,args);
                    case UPDATE:
                        return sqlSession.update(statementId,args);
                    case DELETE:
                        return sqlSession.delete(statementId,args);
                    default:
                        return null;
                }
            }
        });
        return (T)proxyInstance;
    }


}
